package com.qikux.filter;

import com.alibaba.fastjson.JSONArray;
import com.qikux.annotition.Authentication;
import com.qikux.consts.AppConst;
import com.qikux.handler.HandlerMapping;
import com.qikux.handler.RequestHandlerMapping;
import com.qikux.maping.MethodMapping;
import com.qikux.vo.ResultVo;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * 登录认证过滤器
 */
@WebFilter("/*")
public class AuthenticationFilter extends HttpFilter {

    @Override
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

        // 1. 获取 请求 urlpattern
        // 获取请求的地址
        String requestURI = request.getRequestURI();
        // 获取项目名
        String projectPath = request.getContextPath();
        // 获取 UrlPattern
        String urlPattern = requestURI.substring(projectPath.length());

        HandlerMapping mapping = RequestHandlerMapping.getInstance();
        // RequestMapping 容器 包含 method ,  obj , 参数列表
        // 根据请求地址 和 请求方式 找到唯一的 MethodMapping
        MethodMapping methodMapping = mapping.findRequestMappingByUrlPatternAndMethod(urlPattern, request.getMethod());

        if (methodMapping == null) {
            // 如果找不到，则直接 继续 下一个链中执行代码
            chain.doFilter(request, response);
            return;
        }

        // 获取 对应的 请求方法
        Method method = methodMapping.getMethod();

        // 判断 请求方法上 是否有 @Authentication 注解
        if (!method.isAnnotationPresent(Authentication.class)) {
            // 如果找不到，则直接 继续 下一个链中执行代码
            chain.doFilter(request, response);
            return;
        }

        // 如果 有注解、则 判断 当前 session中是否有登录标记
        Object user = request.getSession().getAttribute(AppConst.LOGIN_FLAG);
        // 如果 对象存在，则代表已经登录
        if (user != null) {
            // 如果找不到，则直接 继续 下一个链中执行代码
            chain.doFilter(request, response);
            return;
        }

        // 获取 当前访问的请求地址的来源
        String referer = request.getHeader("referer") ;

        String url = projectPath + "/user/login";

        // 将 请求的来源 以 参数的形式 写再网址上
        if(referer !=null && !"".equals(referer)) {
            // 判断 来源是否是 登录请求
            URL $url = new URL(referer);

            if (!$url.getPath().equals(url)) {
                url+= "?url=" + URLEncoder.encode(referer, StandardCharsets.UTF_8) ;
            }else{
                url = referer ;
            }
        }
        // 判断请求是否是异步请求
        if ("XMLHttpRequest".equals(request.getHeader("x-requested-with"))) {

            // 1. 设置状态码 为 401
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

            // 2. 返回一个 JSON
            ResultVo<Map<String, Object>> resultVo =  ResultVo.fail("未登录")
                    .body(Map.of("loginUrl" , url));

            // 3. 转成 JSON
            String jsonString = JSONArray.toJSONString(resultVo);
            // 4. 响应 JSON格式的内容
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(jsonString);
            return ;
        }
        // 如果对象 不存在 ， 则代表 没有登录, 重定向到登录页面
        response.sendRedirect(url);
    }

}
